/*
 * Copyright (C) 2012 artit91
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be uscful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package rpg.entities.eventhandlers;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.Random;
import java.util.logging.Logger;
import rpg.Game;
import rpg.Location;
import rpg.entities.factories.CreatureFactory;
import rpg.entities.properties.CreatureProperty;
import rpg.entities.Sprite;
import rpg.entities.factories.CritterFactory;
import rpg.entities.factories.SpriteFactory;
import rpg.gfx.Bitmap;
import rpg.gfx.Screen;
import rpg.gfx.Screen.Renderable;
import rpg.util.AStar;

/**
 *
 * @author artit91
 */
public class FollowIfAttacked extends EventHandler {

	private AStar as;
	private LinkedList<Location> path;
	private int nextCheck = 3;
	private int animDelay = 5;
	private int animState = 0;
	private int dir = 0;
	private int damageDelay = 0;
	private CreatureFactory cf;
	private CreatureProperty cp;

	public FollowIfAttacked(final CreatureFactory cf) {
		this.cf = cf;
		this.cp = (CreatureProperty) cf.getProp();
		as = new AStar();
	}

	@Override
	public void tick() {

		if (damageDelay > 0) {
			damageDelay--;
		}

		if (cp.getTargetEntity() != null) {
			double dist = cp.getLocation().getDistance(cp.getTargetEntity().getProp().getLocation());
			if (dist < 34) {
				attack();
				return;
			} else if (dist > 320) {
				cp.setTargetEntity(null);
				path.clear();
				return;
			}
			if (path == null || path.isEmpty() || nextCheck <= 0) {
				path = as.getPath(cp.getLocation(), cp.getTargetEntity().getProp().getLocation(), cf.getMap());
				nextCheck = 3;
			}
			if (path == null || cp.getLocation() == null) {
				return;
			}
			cp.setNextMove(path.getFirst().normalize(cp.getLocation()));
			if (cp.getLocation().equals(path.getFirst(), cp.getSpeed())) {
				path.removeFirst();
				nextCheck--;
			}
			cp.setSpeed(2);
		} else {
			cp.setSpeed(1);
			Screen.Renderable r = Screen.getInstance().new Renderable(
				Game.getInstance().getActual(),
				SpriteFactory.getInstance(0).getProp().getLocation().getX() + SpriteFactory.getInstance(0).getxRenderOffset(),
				SpriteFactory.getInstance(0).getProp().getLocation().getY() + SpriteFactory.getInstance(0).getyRenderOffset());
			for (Iterator<SpriteFactory> it = SpriteFactory.getEntites().iterator(); it.hasNext();) {
				SpriteFactory s;
				try {
					s = it.next();
				} catch (Exception ex) {
					//if deleted when accessed
					break;
				}
				if (s instanceof CritterFactory
					&& s.getProp().getLocation().getDistance(cp.getLocation()) < 300
					&& s.isInView(r) && cf.isInView(r)) {
					cp.setTargetEntity(s);
					break;
				}
			}
		}
		animDelay--;
		if (animDelay <= 0) {
			animDelay = 5;
			animState++;
			animState %= 3;
		}
		int moveDir = cp.getLocation().getDir(cp.getNextMove());
		if (moveDir != -1) {

			dir = moveDir;
			if (!cp.getLocation().move(moveDir, cp.getSpeed())) {
				if (cp.getTargetEntity() != null) {
					path = as.getPath(cp.getLocation(), ((CreatureProperty) cp.getTargetEntity().getProp()).getNextMove(), cf.getMap());
				} else {
					cp.setNextMove(cp.getLocation().getPossibleLocation(cf.getMap()));
				}
			}
		} else {
			Random rand = new Random();
			if (rand.nextBoolean()) {
				cp.setNextMove(cp.getLocation().getPossibleLocation(cf.getMap()));
			}
		}

		if (damageDelay > 0) {
			damageDelay--;
		}
	}

	public void attack() {
		if (damageDelay != 0) {
			return;
		}
		if (cp.getTargetEntity() != null) {
			damageDelay = 30;
			Random r = new Random();
			int dmg = r.nextInt(10) + 10;
			boolean damage = cp.getTargetEntity().getEh().damage(cf, dmg);
			if (damage) {
				if (cp.getTargetEntity().getProp() != null) {
					SpriteFactory.remove(cp.getTargetEntity().getProp().getId());
				}
				cp.setTargetEntity(null);
				path.clear();
			}
		}
	}

	@Override
	public boolean damage(Sprite causer, int dmg) {
		if (((CreatureProperty) cf.getProp()).getHealth() - dmg <= 0) {
			((CreatureProperty) cf.getProp()).setHealth(0);
		} else {
			((CreatureProperty) cf.getProp()).setHealth(((CreatureProperty) cf.getProp()).getHealth() - dmg);
			cf.getHealthBar().setVal(((CreatureProperty) cf.getProp()).getHealth());
		}
		//lastDamagedBy = causer;
		cp.setTargetEntity(causer);
		return ((CreatureProperty) cf.getProp()).getHealth() == 0;
	}

	@Override
	public Bitmap getDrawGraphics() {
		return cf.bitmaps[animState % 3 + dir * 3];
	}
	private static final Logger LOG = Logger.getLogger(FollowIfAttacked.class.getName());
}
